﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Alysa
{
    public abstract class Plugin
    {
        private String NameOfPlugin;
        private PluginInputData InputData;
        private PluginExecutionResult Result = new PluginExecutionResult(PluginExecutionResult.STATUS.NEVER_RUN, 0);
        private Thread mThread = null;
        private object mLock = new object();
        private volatile bool mShouldStop = false;
        bool mInitialized = false;

        public virtual void Initialize(String name)
        {
            NameOfPlugin = name;
            mInitialized = true;
        }

        public Plugin() { }

        public String getName() { return NameOfPlugin; }

        public virtual void start(PluginInputData iInput)
        {
            lock (mLock)
            {
                InputData = iInput;
                mThread = new Thread(new ThreadStart(asyncExecute));
                Result.setStatus(PluginExecutionResult.STATUS.IN_PROGRESS);
                mShouldStop = false;
                mThread.Start();
            }
        }

        public virtual void RequestStop()
        {
            mShouldStop = true;
        }

        public virtual bool ShouldStop()
        {
            return mShouldStop;
        }

        public virtual void SetShouldStop(bool iVal)
        {
            mShouldStop = iVal;
        }

        public virtual void stop()
        {
            lock (mLock)
            {
                if (mThread != null
                    && mThread.IsAlive)
                {
                    mThread.Abort();
                }
            }
        }

        public abstract PluginExecutionResult execute(PluginInputData iInput);

        public virtual PluginExecutionResult getResult() { return Result; }

        protected virtual void asyncExecute()
        {
           // Object[] args = { InputData };
            try
            {
                PluginExecutionResult wResult = execute(InputData);//(PluginExecutionResult)DynaInvoke.InvokeMethod(AddressOfDll, NameOfPluginClass, "execute", args);
                Result = wResult;
            }
            catch (ExecutionRequestedToStopException)
            {
                Result = new PluginExecutionResult(PluginExecutionResult.STATUS.CANCELLED, 0);
            }
            catch (ThreadAbortException)
            {
                Result = new PluginExecutionResult(PluginExecutionResult.STATUS.STOPPED, 0);
            }
            catch (Exception e)
            {
                Result = new PluginExecutionResult(PluginExecutionResult.STATUS.FAIL, 0);
            }
        }
    }
}
